"""
@file: Auth.py
@author: lingdubing
@time: 2024/11/08  9:48
@desc: 安全验证类
@character: utf-8
"""
from typing import Optional
import jwt
import datetime
from config import settings
from service.UserService import UserService
from service.UserRoleLinkService import UserRoleService
from service.AccessService import AccessService
from service.RoleAccessService import RoleAccessService
from schemas.response import STATUS_CODE
from fastapi import Header, HTTPException, Depends, Request


# 基于电话号码和时间戳生成验证token
def generate_token(phone: str):
    timestamp = int(datetime.datetime.utcnow().timestamp())  # 当前时间戳
    # 计算过期时间戳（秒级）
    expiration_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=60)  # 当前时间戳加上一小时

    data = {'username': phone, 'exp': expiration_time, 'timestamp': timestamp}

    token = jwt.encode(payload=data, key=settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
    return token


async def verify_token(authorization: Optional[str] = Header(None)):
    """
    token验证
    :param authorization:
    :return:
    """
    # ----------------------------------------验证JWT token------------------------------------------------------------

    try:
        if not authorization:
            credentials_exception = HTTPException(
                status_code=STATUS_CODE["unauthorized"],
                detail="无效凭证",
                headers={"WWW-Authenticate": f"Bearer"},
            )
            raise credentials_exception

        if not authorization.startswith("Bearer "):
            credentials_exception = HTTPException(
                status_code=STATUS_CODE["unauthorized"],
                detail="无效凭证",
                headers={"WWW-Authenticate": f"Bearer"},
            )
            raise credentials_exception

        ver_token = authorization[7:]

        # token解密
        payload = jwt.decode(
            ver_token,
            settings.JWT_SECRET_KEY,
            algorithms=[settings.JWT_ALGORITHM]
        )

        if payload:
            # 用户电话号
            username = payload.get("username", None)
            # 无效用户信息
            if username is None:
                credentials_exception = HTTPException(
                    status_code=STATUS_CODE["unauthorized"],
                    detail="无效凭证",
                    headers={"WWW-Authenticate": f"Bearer{ver_token}"},
                )
                raise credentials_exception
            else:
                user_service = UserService()
                user_info = user_service.get_user_by_username(username)
                if user_info.user_status == 0 or user_info is None:
                    credentials_exception = HTTPException(
                        status_code=STATUS_CODE["unauthorized"],
                        detail="无效凭证,无用户信息",
                        headers={"WWW-Authenticate": f"Bearer{ver_token}"},
                    )
                    raise credentials_exception
                user_role_service = UserRoleService()
                user_role = user_role_service.get_user_role_link(user_info.user_id)
                if user_role is None:
                    credentials_exception = HTTPException(
                        status_code=STATUS_CODE["unauthorized"],
                        detail="无效凭证，无角色分配",
                        headers={"WWW-Authenticate": f"Bearer{ver_token}"},
                    )
                    raise credentials_exception
                return user_info.user_id,user_role.role_id
        else:
            credentials_exception = HTTPException(
                status_code=STATUS_CODE["unauthorized"],
                detail="无效凭证",
                headers={"WWW-Authenticate": f"Bearer {ver_token}"},
            )
            raise credentials_exception

    except jwt.ExpiredSignatureError:

        raise HTTPException(
            status_code=STATUS_CODE["unauthorized"],
            detail="凭证已证过期",
            headers={"WWW-Authenticate": f"Bearer {ver_token}"},
        )

    except jwt.InvalidTokenError:

        raise HTTPException(
            status_code=STATUS_CODE["unauthorized"],
            detail="无效凭证",
            headers={"WWW-Authenticate": f"Bearer {ver_token}"},
        )


async def check_permission(request: Request, user_info: tuple = Depends(verify_token)):
    "“"
    "检查接口权限"
    "“"
    user_id, role_id = user_info
    permission_name = request.url.path.split('/')[-1]
    role_access = RoleAccessService()
    access = AccessService()
    access_list = role_access.get_access_by_role(role_id)
    access_scopes_list = []
    for var in access_list:
        access_info = access.get_access_by_id(var.access_id)
        access_scopes_list.append(access_info.access_url)

    role_access.close()
    access.close()
    if permission_name not in access_scopes_list:
        credentials_exception = HTTPException(
            status_code=STATUS_CODE["unauthorized"],
            detail="没有权限",
            headers={"WWW-Authenticate": "Bearer"}
        )
        raise credentials_exception
    else:
        return user_id,role_id


